package tetris.game;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;

import tetris.game.menu.GenericMenu;
import tetris.game.model.Game;
import tetris.game.view.TetrisGLView;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ArrayAdapter;
import android.widget.Toast;

public class MucisMultiplayerActivity extends Activity {
	
//	private final String SERVICE_NAME = "MultiPlayerTetrisMUC";
	
//	private final UUID TETRIS_UUID = UUID.fromString("4080ad8d-8ba2-4846-8803-a3206a8975be");
	
	// Debugging
    private static final String TAG = "MucisMultiplayerActivity";
    private static final boolean D = true;

    // Message types sent from the BluetoothChatService Handler
    public static final int MESSAGE_STATE_CHANGE = 1;
    public static final int MESSAGE_READ = 2;
    public static final int MESSAGE_WRITE = 3;
    public static final int MESSAGE_DEVICE_NAME = 4;
    public static final int MESSAGE_TOAST = 5;
    
    // Intent request codes
    private static final int REQUEST_CONNECT_DEVICE_SECURE = 1;
    private static final int REQUEST_CONNECT_DEVICE_INSECURE = 2;
    private static final int REQUEST_ENABLE_BT = 3;
	
	private TetrisGLView view;
	private GLSurfaceView mGLView;
	private GenericMenu gM;
	private int width, height;
	
	private Game game;
	private MPGameLoopThread mpGameLoopThread;
	
	private Handler handler;
	
	/**
	 * This Map keeps the names and MAC addresses of all found (paired and unpaired) devices in range 
	 */
	private Map<String, String> foundDevices = new HashMap<String, String> ();
	
	private BluetoothServerSocket serverSocket = null;
	
	private BluetoothSocket socket = null;
	
	private BluetoothDevice device = null;
	
	private BluetoothService bluetoothService = null;
	
	private BluetoothAdapter bluetoothAdapter = null;
	
	// Create a BroadcastReceiver for ACTION_FOUND to find unpaired local devices
/*	private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
	    public void onReceive(Context context, Intent intent) {
	        String action = intent.getAction();
	        // When discovery finds a device
	        if (BluetoothDevice.ACTION_FOUND.equals(action)) {
	            // Get the BluetoothDevice object from the Intent
	            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
	            // Add the name and address to an array adapter to show in a ListView
	            foundDevices.put(device.getName(), device.getAddress());
	        }
	    }
	};
*/	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        this.width = this.getWindowManager().getDefaultDisplay().getWidth();
        this.height = this.getWindowManager().getDefaultDisplay().getHeight();
        
	    handler = new Handler();
	    
	    
	    // Get local Bluetooth adapter
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        // If the adapter is null, then Bluetooth is not supported
        if (bluetoothAdapter == null) {
            Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
            finish();
            return;
        }
        
     // set audio volume to maximum 
	    // Get the AudioManager
	    /*	AudioManager audioManager = 
	    	(AudioManager)this.getSystemService(Context.AUDIO_SERVICE);
	    	// Set the volume of played media to maximum.
	    	audioManager.setStreamVolume (AudioManager.STREAM_MUSIC,
	    			audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC), 0);	*/
	    
	    // If BT is not on, request that it be enabled.
        if (!BluetoothAdapter.getDefaultAdapter().isEnabled()) {
            Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
        // Otherwise, setup the chat session
        }
        
	    // Use DeviceListActivity to let user choose a device to connect with
	    ensureDiscoverable();
	    Log.i("MucisMultiplayerActivity", "DeviceListActivity started");
    	Intent intent = new Intent(this, DeviceListActivity.class);
    	startActivityForResult(intent, 1);
    	
    	// Retrieve the MAC address gotten from DeviceListActivity
/*	    Bundle extras = intent.getExtras(); 
	    String macAddress = extras.getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
	    // finish Activity if no address could be retrieved
    	if(macAddress == null)
    		finish();
*/	    
	    // first create the MPGameLoopThread (to access its handler)
	    game = new Game();
		view = new TetrisGLView(this, game);
	    mGLView = view;
	    this.mpGameLoopThread = new MPGameLoopThread(this, mGLView, game);
	    this.handler = mpGameLoopThread.getHandler();
	    // create the bluetooth service with the handler of the game loop thread
	    this.bluetoothService = new BluetoothService(this, this.handler);
	    // set the bluetooth service at the game loop thread
	    this.mpGameLoopThread.setBluetoothService(this.bluetoothService);
	    
	    // make the actual connection to the remote device if one has been selected in DeviceListActivity
	    // Get the BluetoothDevice object
/*	    if(macAddress != null) {
	    	BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(macAddress); 
	    	this.bluetoothService.connect(device, false);
	    }
	    // otherwise start the server
	    else {
	    	this.bluetoothService.start();
	    	
	    }
*/
	//    gameLoopThread = new GameLoopThread(this, mGLView, game, handler, socket);
	//    mpGameLoopThread.start();
	    
	    setContentView(mGLView);
    }
    
    @Override
    protected void onPause() {
    	super.onPause();
    	mGLView.onPause();
    }
    
    @Override
    protected void onResume() {
    	super.onResume();
    	mGLView.onResume();
    }
    
    @Override
	protected void onDestroy() {
		super.onDestroy();
		mGLView.onPause();
		if(socket != null) {
			try {
				socket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		if(serverSocket != null) {
			try {
				serverSocket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
    
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(D) Log.d(TAG, "onActivityResult " + resultCode);
        switch (requestCode) {
        case REQUEST_CONNECT_DEVICE_SECURE:
            // When DeviceListActivity returns with a device to connect
            if (resultCode == Activity.RESULT_OK) {
                connectDevice(data, true);
            }
            break;
        case REQUEST_CONNECT_DEVICE_INSECURE:
            // When DeviceListActivity returns with a device to connect
            if (resultCode == Activity.RESULT_OK) {
                connectDevice(data, false);
            }
            break;
        case REQUEST_ENABLE_BT:
            // When the request to enable Bluetooth returns
            if (resultCode == Activity.RESULT_OK) {
                // Bluetooth is now enabled, so start the game loop thread
            	Log.d(TAG, "Start the GameLoopThread");
                this.mpGameLoopThread.start();
            } else {
                // User did not enable Bluetooth or an error occurred
                Log.d(TAG, "BT not enabled");
       //         Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show();
                finish();
            }
        }
    }

    private void connectDevice(Intent data, boolean secure) {
        // Get the device MAC address
        String address = data.getExtras()
            .getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
        // Get the BluetoothDevice object
        BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address);
        // Attempt to connect to the device
        this.bluetoothService.connect(device, secure);
    }
    
    private void ensureDiscoverable() {
        if(D) Log.d(TAG, "ensure discoverable");
        if (BluetoothAdapter.getDefaultAdapter().getScanMode() !=
            BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
            Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
            discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
            startActivity(discoverableIntent);
        }
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    	gM = new GenericMenu(menu);
    	gM.populate();
    	return super.onCreateOptionsMenu(menu);
    }
    
    @Override
    public boolean onMenuItemSelected(int featureId, MenuItem item) {
    	if (item.getTitle().equals("Restart")) {
    		// create new game
    		game = new Game();
    		mpGameLoopThread.setGame(game);
    		view.game = game;
    		
    		// init
    		mpGameLoopThread.setShowGOMessage(true);
    	}
    	
    	if (item.getTitle().equals("Quit")) {
    		mpGameLoopThread.setRunning(false);
    		mpGameLoopThread.destroy();
    		this.setResult(1, new Intent());
    		this.finish();
    	}
    	
    	return super.onMenuItemSelected(featureId, item);
    }
}